#region Using References

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using Beaker.OpenCube.Game;

#endregion

namespace Beaker.OpenCube.Textures
{
	/// <summary>
	/// All textures for a single block
	/// </summary>
	public sealed class BlockTexture
	{
		private readonly Block _block;
		private readonly Texture[] _blockTextures;
		private readonly TextureIndexer _textureIndexer;

		public BlockTexture( Block block, IEnumerable<Tuple<BlockTextureFlags, Texture>> textures )
		{
			Contract.Requires<ArgumentNullException>( textures != null );

			// convert list of textures to a 'flat' map for all flags
			// this allowes quick retrieval of correct texture for any type of texture
			_blockTextures = new Texture[(int)BlockTextureFlags.MaxValue + 1];
			foreach( Tuple<BlockTextureFlags, Texture> textureMapping in textures )
			{
				for( int i = 1; i < (int)BlockTextureFlags.MaxValue; i++ )
				{
					// check if this texture is part of this mapping
					if( ( (int)textureMapping.Item1 & i ) == i )
					{
						_blockTextures[i] = textureMapping.Item2;
					}
				}
			}

			_block = block;
			_textureIndexer = new TextureIndexer( _blockTextures );
		}

		/// <summary>
		/// Gets the block these textures are for.
		/// </summary>
		/// <value>
		/// The block these textures are for.
		/// </value>
		public Block Block
		{
			get { return _block; }
		}

		/// <summary>
		/// Gets the textures for this block.
		/// </summary>
		/// <value>
		/// The textures for this block.
		/// </value>
		public TextureIndexer Textures
		{
			get { return _textureIndexer; }
		}

		public class TextureIndexer
		{
			private readonly Texture[] _blockTextures;

			internal TextureIndexer( Texture[] blockTextures )
			{
				Contract.Requires<ArgumentNullException>( blockTextures != null );
				Contract.Requires<ArgumentNullException>( blockTextures.Length == (int)BlockTextureFlags.MaxValue + 1 );
				Contract.Ensures( _blockTextures == blockTextures );

				_blockTextures = blockTextures;
			}

			/// <summary>
			/// Gets the texture for the given flags combination
			/// </summary>
			/// <param name="flags">The flags combination to get the texture for</param>
			/// <returns>The texture for the requested flags combination, or <c>null</c> when there is no texture for the given combination.</returns>
			public Texture this[BlockTextureFlags flags]
			{
				get
				{
					return _blockTextures[(int)flags];
				}
			}
		}
	}
}